package mongo

import (
	"context"
	"core/corestruct"
	"core/datetime"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo/options"
	"log"
	"time"
)

/*
mongo分页，只能id 倒序
https://blog.csdn.net/m0_56137272/article/details/132629538
*/
type PageDtService[T any] struct {
	ColBaseName string
	Filer       bson.M
	Dtb         time.Time
	Dte         time.Time
	PageNo      int
	PageSize    int
}

func (p *PageDtService[T]) Page() (*corestruct.Page[T], error) {
	var mp, err = p.count()
	if err != nil {
		return nil, err
	}
	var r = &corestruct.Page[T]{}
	r.TotalRow = 0
	r.PageNumber = p.PageNo
	r.PageSize = p.PageSize
	r.Records = make([]T, 0)

	var skip = int64((r.PageNumber - 1) * r.PageSize)
	for _, v := range mp {
		r.TotalRow += v.V1
	}

	for _, v := range mp {

		if v.V1 == 0 {
			continue
		}

		if skip >= v.V1 {
			skip -= v.V1
			continue
		}

		var take = r.PageSize
		take -= len(r.Records)
		
		var data, err = p.list(v.Id, skip, int64(take))
		if err != nil {
			return nil, err
		}
		for _, row := range data {
			r.Records = append(r.Records, row)
		}
		if len(r.Records) >= r.PageSize {
			break
		}
	}

	return r, nil
}
func (p *PageDtService[T]) count() ([]corestruct.KvInt64Model, error) {
	var mp = make([]corestruct.KvInt64Model, 0)
	for dt := p.Dte.AddDate(0, 0, -1); dt.Unix() >= p.Dtb.Unix(); dt = dt.AddDate(0, 0, -1) {
		var shortdt = datetime.FormatDate(dt)
		var colname = p.ColBaseName + shortdt
		var col = Db.Collection(colname)
		c, err := col.CountDocuments(context.Background(), p.Filer)
		if err != nil {
			return nil, err
		}
		mp = append(mp, corestruct.KvInt64Model{Id: shortdt, V1: c})
	}

	return mp, nil
}
func (p *PageDtService[T]) list(shortdt string, skip int64, take int64) ([]T, error) {
	var r = make([]T, 0)
	var colname = p.ColBaseName + shortdt
	var col = Db.Collection(colname)

	opts := options.Find().SetSort(bson.D{{"_id", -1}}).
		SetSkip(skip).
		SetLimit(take)

	var cur, err = col.Find(context.Background(), p.Filer, opts)
	if err != nil {
		log.Fatal(err)
	}
	defer cur.Close(context.Background())
	for cur.Next(context.Background()) {
		var m T
		err := cur.Decode(&m)
		if err != nil {
			log.Fatal(err)
		}
		r = append(r, m)
	}

	return r, nil
}
